// Learn cc.Class:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/class.html
//  - [English] http://www.cocos2d-x.org/docs/creator/en/scripting/class.html
// Learn Attribute:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/reference/attributes.html
//  - [English] http://www.cocos2d-x.org/docs/creator/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html
//  - [English] http://www.cocos2d-x.org/docs/creator/en/scripting/life-cycle-callbacks.html

import { _decorator, Prefab, Node, instantiate, NodePool, Asset, isValid } from "cc";
import { DEBUG } from "cc/env";
import { Debug } from "../../utils/Debug";
import { poolComponent } from "./poolComponent";
const { ccclass, property } = _decorator;

@ccclass("poolManager")
export class poolManager {
    private static dictPool: { [name: string]: NodePool } = {}
    private static dictPrefab: { [name: string]: Prefab } = {}
    private static dictStack: { [name: string]: Array<Node> } = {}

    public static getPrefab(name: string): Prefab {
        return this.dictPrefab[name];
    }

    public static addPrefab(prefab: Prefab): void {
        this.dictPrefab[prefab.data.name] = prefab;
        if (DEBUG) {
            Debug.log("poolManager addPrefab:", prefab.data.name);
        }
    }
    public static addPrefabs(prefabs: Array<Asset>): void {
        prefabs.forEach((prefab: any) => {
            this.addPrefab(prefab);
        })
    }
    public static getAllPool(): { [name: string]: NodePool } {
        return this.dictPool;
    }

    public static getAllStack(): { [name: string]: Array<Node> } {
        return this.dictStack;
    }

    public static getStack(name: string): Array<Node> {
        if (this.dictStack.hasOwnProperty(name)) {
            return this.dictStack[name];
        }
        return null!;
    }
    /**
     * 根据预设从对象池中获取对应节点
     */
    public static getNode(prefab: Prefab, parent: Node, isWorldTransform: boolean = false): Node {
        let name = prefab.data.name;
        // this.dictPrefab[name] = prefab;
        let node: Node;
        if (this.dictPool.hasOwnProperty(name)) {
            //已有对应的对象池
            let pool = this.dictPool[name];
            if (pool.size() > 0) {
                node = pool.get()!;
            } else {
                node = instantiate(prefab);
            }
        } else {
            //没有对应对象池，创建他！
            let newPool = new NodePool();
            if (newPool)
                this.dictPool[name] = newPool;
            else {
                console.error('创建对象池错误', newPool)
            }

            node = instantiate(prefab);
        }
        if (isValid(parent))
            node.setParent(parent, isWorldTransform);
        if (!this.dictStack.hasOwnProperty(name)) {
            this.dictStack[name] = [];
        }
        this.dictStack[name].push(node);

        return node;
    }

    /**
     * 将对应节点放回对象池中
     */
    public static putNode(node: Node): void {
        let pc = node.getComponent(poolComponent);
        let tag = pc.tag;
        let pool = null;
        if (this.dictPool.hasOwnProperty(tag)) {
            //已有对应的对象池
            pool = this.dictPool[tag];
        } else {
            //没有对应对象池，创建他！
            pool = new NodePool();
            this.dictPool[tag] = pool;
        }
        this.removeStack(node);
        pool.put(node);
    }

    /**
     * 根据名称，清除对应对象池
     */
    public static clearPool(name: string): void {
        if (this.dictPool.hasOwnProperty(name)) {
            let pool = this.dictPool[name];
            pool.clear();
        }
    }

    public static removeStackByName(name: string) {
        if (this.dictStack.hasOwnProperty(name)) {
            let stack = this.dictStack[name];
            stack.splice(0, stack.length);
        }
    }

    public static removeStack(removeItem: Node) {
        for (var k in this, this.dictStack) {
            if (this.dictStack.hasOwnProperty(k)) {
                let stack = this.dictStack[k];
                let index = stack.indexOf(removeItem);
                if (index != -1) {
                    stack.splice(index, 1);
                    break;
                }
            }
        }
    }
    public static removeStackAll(removeItem: Node) {
        for (var k in this, this.dictStack) {
            if (this.dictStack.hasOwnProperty(k)) {
                let stack = this.dictStack[k];
                let index = stack.indexOf(removeItem);
                if (index != -1) {
                    stack.splice(index, 1);
                }
            }
        }
    }

    // update (deltaTime: number) {
    //     // Your update function goes here.
    // }
}
